package com.example.serverdemo.bean;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ArrayUtil;
import com.example.serverdemo.utils.crcutls.CRC16Tool;
import com.example.serverdemo.utils.crcutls.CRCUtil;
import com.example.serverdemo.utils.stringutils.StringUtils;
import org.springframework.core.codec.EncodingException;

import javax.sound.sampled.AudioFormat;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.zip.CRC32;

public class HardwareParameterBean {
    private int ver;
    private int playFlag;
    private int sumUseTime;
    private int diskFlag;
    private String deviceName;
    private int addr;
    private int linkMode;
    private int linkPort;
    private String ip;
    private String netMask;
    private String gateWay;
    private String mac;
    private int baud;
    private int currUseTime;
    private String remoteHost;
    private int remotePort;
    private String domainName;
    private String domainServer;
    private String hardwareId;
    private String heartbeat;
    private int heartbeatCycle;
    private String deviceId;

    public byte[] toHexData() throws UnsupportedEncodingException {
        byte[] buff;
        String[] strArray;
        List<Byte> data = new ArrayList<>();
        //Flag
        data.add(Convert.intToByte(0xEA));
        //Ver
        data.add(Convert.intToByte(this.ver));
        //PlayFlag
        data.add(Convert.intToByte(this.playFlag));
        //SumUseTimes
        buff = Convert.intToBytes(this.sumUseTime);
        data.add(buff[3]);
        data.add(buff[2]);
        data.add(buff[1]);
        data.add(buff[0]);
        //DiskFlag
        data.add(Convert.intToByte(this.diskFlag));
        //DeviceName
        buff = this.deviceName.getBytes("GBK");
        for (int i = 0;i < 16;i++){
            if (i >= buff.length) data.add(Convert.intToByte(0x00));
            else data.add(buff[i]);
        }
        //Addr
        data.add(Convert.intToByte(this.addr));
        //LinkMode
        data.add(Convert.intToByte(this.linkMode));
        //LinkPort
        buff = Convert.intToBytes(this.linkPort);
        data.add(buff[3]);
        data.add(buff[2]);
        //IP
        strArray = this.ip.split("\\.");
        for (int i = 0; i < 4;i++){
            data.add(Convert.intToByte(Integer.valueOf(strArray[i])));

        }
        //NetMask
        strArray = this.netMask.split("\\.");
        for (int i = 0; i < 4;i++){
            data.add(Convert.intToByte(Integer.valueOf(strArray[i])));
        }
        //GateWay
        strArray = this.gateWay.split("\\.");
        for (int i = 0; i < 4;i++){
            data.add(Convert.intToByte(Integer.valueOf(strArray[i])));
        }
        //mac
        strArray = this.mac.split("-");
        for (int i = 0; i < 6;i++){
            data.add(Convert.intToByte(Integer.valueOf(strArray[i])));
        }
        //Baud
        data.add(Convert.intToByte(this.baud));
        //CurrUseTimes
        buff = Convert.intToBytes(this.currUseTime);
        data.add(buff[3]);
        data.add(buff[2]);
        data.add(buff[1]);
        data.add(buff[0]);
        //RemoteHost
        strArray = this.remoteHost.split("\\.");
        for (int i = 0; i < 4;i++){
            data.add(Convert.intToByte(Integer.valueOf(strArray[i])));
        }
        //RemotePort;
        buff = Convert.intToBytes(this.remotePort);
        data.add(buff[3]);
        data.add(buff[2]);
        //DomainName
        buff = this.domainName.getBytes("GBK");
        for (int i = 0;i < 32;i++){
            if (i >= buff.length) data.add(Convert.intToByte(0x00));
            else data.add(buff[i]);
        }
        //DomainServer
        strArray = this.domainServer.split("\\.");
        for (int i = 0; i < 4;i++){
            data.add(Convert.intToByte(Integer.valueOf(strArray[i])));
        }
        //HardwareID
        for (int i = 0;i < 32;i = i + 2){
//            data.add(Convert.intToByte(Integer.parseInt("" + this.hardwareId.charAt(i) + this.hardwareId.charAt(i+1),16)));
            data.add(Convert.intToByte(0x30));
        }
        //Heartbeat
        buff = this.heartbeat.getBytes("GBK");
        for (int i = 0;i < 8;i++){
            if (i >= buff.length) data.add(Convert.intToByte(0x00));
            else data.add(buff[i]);
        }
        //HeartbeatCycle
        buff = Convert.intToBytes(this.heartbeatCycle);
        data.add(buff[3]);
        data.add(buff[2]);
        int crc16 = CRCUtil.getInstance().calcCrc16(Convert.toPrimitiveByteArray(data));
        buff = Convert.intToBytes(crc16);
        data.add(buff[3]);
        data.add(buff[2]);
        return Convert.toPrimitiveByteArray(data);
    }

    public static HardwareParameterBean build(byte[] data){
        HardwareParameterBean bean = null;
        try {
            int point = 1;
            List<Byte> buff = new ArrayList<>();
            bean = new HardwareParameterBean();
            bean.ver = Convert.byteToUnsignedInt(data[point++]);
            bean.playFlag = Convert.byteToUnsignedInt(data[point++]);
            bean.sumUseTime = Convert.byteToUnsignedInt(data[point++]) | (Convert.byteToUnsignedInt(data[point++]) << 8) | (Convert.byteToUnsignedInt(data[point++]) << 16) | (Convert.byteToUnsignedInt(data[point++]) << 24);
            bean.diskFlag = Convert.byteToUnsignedInt(data[point++]);
            for (int i = 0;i < 16;i++){
                byte value = data[point++];
                if (value != Convert.intToByte(0x00)) buff.add(value);
            }
            bean.deviceName = new String(Convert.toPrimitiveByteArray(buff),"gbk");
            buff.clear();
            bean.addr = Convert.byteToUnsignedInt(data[point++]);
            bean.linkMode = Convert.byteToUnsignedInt(data[point++]);
            bean.linkPort = Convert.byteToUnsignedInt(data[point++]) | Convert.byteToUnsignedInt (data[point++]) << 8;
            bean.ip = "" + Convert.byteToUnsignedInt(data[point++]) + "." + Convert.byteToUnsignedInt(data[point++]) + "." +Convert.byteToUnsignedInt(data[point++]) + "." +Convert.byteToUnsignedInt(data[point++]);
            bean.netMask = "" + Convert.byteToUnsignedInt(data[point++]) + "." + Convert.byteToUnsignedInt(data[point++]) + "." +Convert.byteToUnsignedInt(data[point++]) + "." +Convert.byteToUnsignedInt(data[point++]);
            bean.gateWay = "" + Convert.byteToUnsignedInt(data[point++]) + "." + Convert.byteToUnsignedInt(data[point++]) + "." +Convert.byteToUnsignedInt(data[point++]) + "." +Convert.byteToUnsignedInt(data[point++]);
            bean.mac = "" + Convert.byteToUnsignedInt(data[point++]) + "-" + Convert.byteToUnsignedInt(data[point++]) + "-" +Convert.byteToUnsignedInt(data[point++]) + "-" +Convert.byteToUnsignedInt(data[point++]) + "-" +Convert.byteToUnsignedInt(data[point++]) + "-" +Convert.byteToUnsignedInt(data[point++]);
            bean.baud = Convert.byteToUnsignedInt(data[point++]);
            bean.currUseTime = Convert.byteToUnsignedInt(data[point++]) | (Convert.byteToUnsignedInt(data[point++]) << 8) | (Convert.byteToUnsignedInt(data[point++]) << 16) | (Convert.byteToUnsignedInt(data[point++]) << 24);
            bean.remoteHost = "" + Convert.byteToUnsignedInt(data[point++]) + "." + Convert.byteToUnsignedInt(data[point++]) + "." +Convert.byteToUnsignedInt(data[point++]) + "." +Convert.byteToUnsignedInt(data[point++]);
            bean.remotePort = Convert.byteToUnsignedInt(data[point++]) | (Convert.byteToUnsignedInt(data[point++]) << 8);
            for (int i = 0;i < 32;i++){
                byte value = data[point++];
                if (value != Convert.intToByte(0x00)) buff.add(value);
            }
            bean.domainName = new String(Convert.toPrimitiveByteArray(buff),"gbk");
            buff.clear();
            bean.domainServer = "" + Convert.byteToUnsignedInt(data[point++]) + "." + Convert.byteToUnsignedInt(data[point++]) + "." +Convert.byteToUnsignedInt(data[point++]) + "." +Convert.byteToUnsignedInt(data[point++]);
            for (int i = 0;i < 16;i++){
                buff.add(data[point++]);
            }
            bean.hardwareId = Convert.toHex(Convert.toPrimitiveByteArray(buff)).toUpperCase(Locale.ROOT);
            buff.clear();
            for (int i = 0;i < 8;i++){
                byte value = data[point++];
                if (value != Convert.intToByte(0x00)) buff.add(value);
            }
            bean.heartbeat = new String(Convert.toPrimitiveByteArray(buff));
            buff.clear();
            bean.heartbeatCycle = Convert.byteToUnsignedInt(data[point++]) | (Convert.byteToUnsignedInt(data[point++]) << 8);
        }catch (Exception e){

        }
        return bean;
    }

    public int getVer() {
        return ver;
    }
    public void setVer(int ver) {
        this.ver = ver;
    }
    public int getPlayFlag() {
        return playFlag;
    }
    public void setPlayFlag(int playFlag) {
        this.playFlag = playFlag;
    }
    public int getSumUseTime() {
        return sumUseTime;
    }
    public void setSumUseTime(int sumUseTime) {
        this.sumUseTime = sumUseTime;
    }
    public int getDiskFlag() {
        return diskFlag;
    }
    public void setDiskFlag(int diskFlag) {
        this.diskFlag = diskFlag;
    }
    public String getDeviceName() {
        return deviceName;
    }
    public void setDeviceName(String deviceName) {
        this.deviceName = deviceName;
    }
    public int getAddr() {
        return addr;
    }
    public void setAddr(int addr) {
        this.addr = addr;
    }
    public int getLinkMode() {
        return linkMode;
    }
    public void setLinkMode(int linkMode) {
        this.linkMode = linkMode;
    }
    public int getLinkPort() {
        return linkPort;
    }
    public void setLinkPort(int linkPort) {
        this.linkPort = linkPort;
    }
    public String getIp() {
        return ip;
    }
    public void setIp(String ip) {
        this.ip = ip;
    }
    public String getNetMask() {
        return netMask;
    }
    public void setNetMask(String netMask) {
        this.netMask = netMask;
    }
    public String getGateWay() {
        return gateWay;
    }
    public void setGateWay(String gateWay) {
        this.gateWay = gateWay;
    }
    public String getMac() {
        return mac;
    }
    public void setMac(String mac) {
        this.mac = mac;
    }
    public int getBaud() {
        return baud;
    }
    public void setBaud(int baud) {
        this.baud = baud;
    }
    public int getCurrUseTime() {
        return currUseTime;
    }
    public void setCurrUseTime(int currUseTime) {
        this.currUseTime = currUseTime;
    }
    public String getRemoteHost() {
        return remoteHost;
    }
    public void setRemoteHost(String remoteHost) {
        this.remoteHost = remoteHost;
    }
    public int getRemotePort() {
        return remotePort;
    }
    public void setRemotePort(int remotePort) {
        this.remotePort = remotePort;
    }
    public String getDomainName() {
        return domainName;
    }
    public void setDomainName(String domainName) {
        this.domainName = domainName;
    }
    public String getDomainServer() {
        return domainServer;
    }
    public void setDomainServer(String domainServer) {
        this.domainServer = domainServer;
    }
    public String getHardwareId() {
        return hardwareId;
    }
    public void setHardwareId(String hardwareId) {
        this.hardwareId = hardwareId;
    }
    public String getHeartbeat() {
        return heartbeat;
    }
    public void setHeartbeat(String heartbeat) {
        this.heartbeat = heartbeat;
    }
    public int getHeartbeatCycle() {
        return heartbeatCycle;
    }
    public void setHeartbeatCycle(int heartbeatCycle) {
        this.heartbeatCycle = heartbeatCycle;
    }
    public String getDeviceId() {
        return deviceId;
    }
    public void setDeviceId(String deviceId) {
        this.deviceId = deviceId;
    }
}
